#include "sendsignal.h"
#include <stdexcept> // std::exception
#include <math.h>
#include <float.h>

sendsignal::sendsignal() {
  init();
}

sendsignal::~sendsignal() {
}

void sendsignal::init() {
  p_neuron     = null;
  neuron_count = 0;
  layersize    = 0;
  m_min_value  = 0.;
}

void sendsignal::setminvalue(double v)
{
    m_min_value = v;
}

double sendsignal::getminvalue()
{
    return m_min_value;
}

ntype::error_t sendsignal::geterror(const ntype::signal_t*exp_sig)
{
    const int in_size      = layersize;
    const int layers_count = getlayercountmax();
    const int start_index  = getstartneuronidforlayer(layers_count -1);
    double    ret_error    = 0.;
    double    calc_val;
    ntype::signal_t    local_exp_sig;
    ntype::signal_t    outsig;

    for(int icount = 0; icount < in_size; icount ++)
    {
      local_exp_sig = exp_sig[icount];
      outsig = p_neuron[start_index + icount].getAxon().getFSignal();
//      local_exp_sig = (local_exp_sig <= m_min_value) ? ZERO_VALUE : local_exp_sig;
//      outsig = (outsig <= m_min_value) ? ZERO_VALUE : outsig;

//      if(local_exp_sig <= m_min_value && outsig <= m_min_value)
//          calc_val = ZERO_VALUE;
//      else
      {
        calc_val = ((outsig - local_exp_sig) / local_exp_sig);
        calc_val = fabs(calc_val);
      }
      ret_error += calc_val;
//std::cout << "sig_id: "<< signalid <<" err: " << calc_val << " sum error: "<< ret_error << " exp_sig: "<< local_exp_sig << " out_sig: " <<  outsig << std::endl;
//getLog()->print("err: -> %f  : in_sig -> %f : out_sig -> %f\n", ret_error, insig, outsig);
  }
  ret_error = ret_error / in_size;
//  return ret_error < MIN_ERROR_VALUE ? ZERO_VALUE : ret_error;
  return ret_error;
}

void sendsignal::setlayersize(ntype::layerid_t size) {
   layersize = size;
}

ntype::layerid_t sendsignal::getlayersize() {
  return layersize;
}

void sendsignal::setneuronet(neuron *pneuron, ntype::neuroncount_t count) {
  p_neuron     = pneuron;
  neuron_count = count;
}

ntype::neuronid_t sendsignal::getneuronid(ntype::layerid_t layer, ntype::neuroncount_t pos_in_layer) {
  ntype::neuronid_t neuronid = -1;
  ntype::neuronid_t max_neuron_id = (layer + 1) * layersize;
  if(pos_in_layer >= layersize)
    return NONE_NEURON_ID;

  neuronid = getstartneuronidforlayer(layer);
  neuronid = neuronid + pos_in_layer;

  return (neuronid >= max_neuron_id) ? -1 : neuronid;
}

ntype::neuronid_t sendsignal::getstartneuronidforlayer(const ntype::layerid_t layerid) {
    return layerid * layersize;
//  const int neuron_in_layer = neuron_count/layersize;
//  return layerid * neuron_in_layer;
}

ntype::layerid_t sendsignal::getlayercountmax() {
  return neuron_count / layersize;
}
